#include "StdAfx.h"
#include "ZPicking.h"

ZPicking::ZPicking(VOID)
{
}

ZPicking::~ZPicking(VOID)
{
}

RAY ZPicking::Get_Ray()
{
	return m_Ray;
}

VOID ZPicking::Update()
{
	GD3D9DEVICE->GetViewport(&m_vp);
	GD3D9DEVICE->GetTransform(D3DTS_PROJECTION, &m_matProj);

	GetCursorPos(&m_ptCursor);
	ScreenToClient( GWINBASE.Get_hWnd(), &m_ptCursor );

	m_p.x = ( ( ( (m_ptCursor.x - m_vp.X) * 2.0f / (FLOAT)m_vp.Width ) - 1.0f ) - m_matProj._31) / m_matProj._11;
	m_p.y = ( -( ( (m_ptCursor.y - m_vp.Y) * 2.0f / (FLOAT)m_vp.Height ) - 1.0f ) - m_matProj._32) / m_matProj._22;
	m_p.z = 1.0f;

	m_Ray.vPickRayOrig = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_Ray.vPickRayDir = D3DXVECTOR3(m_p.x, m_p.y, 1.0f);

	GD3D9DEVICE->GetTransform(D3DTS_VIEW, &m_matView);
	D3DXMatrixInverse(&m_matViewInverse, NULL, &m_matView);

	D3DXVec3TransformCoord(&m_Ray.vPickRayOrig, &m_Ray.vPickRayOrig, &m_matViewInverse);
	D3DXVec3TransformNormal(&m_Ray.vPickRayDir, &m_Ray.vPickRayDir, &m_matViewInverse);
	D3DXVec3Normalize(&m_Ray.vPickRayDir, &m_Ray.vPickRayDir);

	//= m_p.x * m_matViewInverse._11 + m_p.y * m_matViewInverse._21 + m_p.z * m_matViewInverse._31;
	//= m_p.x * m_matViewInverse._12 + m_p.y * m_matViewInverse._22 + m_p.z * m_matViewInverse._32;
	//= m_p.x * m_matViewInverse._13 + m_p.y * m_matViewInverse._23 + m_p.z * m_matViewInverse._33;
	//GINTERFACE.m_stSplatting.Test2X = m_Ray.vPickRayOrig.x ;//= m_matViewInverse._41;
	//GINTERFACE.m_stSplatting.Test2Y = m_Ray.vPickRayOrig.y ;//= m_matViewInverse._42;
	//GINTERFACE.m_stSplatting.Test2Z = m_Ray.vPickRayOrig.z ;//= m_matViewInverse._43;
}

BOOL ZPicking::CheckTriangleCollision( D3DXVECTOR3 &a_V0, D3DXVECTOR3 &a_V1, D3DXVECTOR3 &a_V2 )
{
	/*D3DXVECTOR3 vecP;
	D3DXVECTOR3 vecE1 = a_V1 - a_V0;
	D3DXVECTOR3 vecE2 = a_V2 - a_V0;

	D3DXVec3Cross( &vecP, &m_Ray.vPickRayDir, &vecE2 );
	FLOAT fDet	= D3DXVec3Dot( &vecE1, &vecP );
	if( fDet > -0.0001f && fDet < 0.0001f )
	{
		return FALSE;
	}

	FLOAT fInvDet = 1.0f / fDet;
	D3DXVECTOR3	vecS	= m_Ray.vPickRayOrig - a_V0;
	FLOAT u	= fInvDet * D3DXVec3Dot( &vecP, &vecS );

	if( u < 0.0f || u > 1.0f )
	{
		return FALSE;
	}

	D3DXVECTOR3 vecQ;
	D3DXVec3Cross( &vecQ, &vecS, &vecE1 );
	FLOAT v	= fInvDet * D3DXVec3Dot( &vecQ, &m_Ray.vPickRayDir );

	if( v < 0.0f || (u + v) > 1.0f )
	{
		return FALSE;
	}

	m_Ray.fT	= fInvDet * D3DXVec3Dot( &vecQ, &vecE2 );
	if(m_Ray.fT < 0.0f)
	{
		return false;
	}

	m_PickPos	= m_Ray.vPickRayOrig + m_Ray.vPickRayDir * m_Ray.fT;
	
	return TRUE;*/

	//---

	// Find vectors for two edges sharing vert0
	D3DXVECTOR3 edge1 = a_V1 - a_V0;
	D3DXVECTOR3 edge2 = a_V2 - a_V0;

	// Begin calculating determinant - also used to calculate U parameter
	D3DXVECTOR3 pvec;
	D3DXVec3Cross( &pvec, &m_Ray.vPickRayDir, &edge2 );

	// If determinant is near zero, ray lies in plane of triangle
	FLOAT det = D3DXVec3Dot( &edge1, &pvec );

	D3DXVECTOR3 tvec;
	if( det > 0 )
	{
		tvec = m_Ray.vPickRayOrig - a_V0;
	}
	else
	{
		tvec = a_V0 - m_Ray.vPickRayOrig;
		det = -det;
	}

	if( det < 0.0001f )
		return FALSE;

	// Calculate U parameter and test bounds
	FLOAT u = D3DXVec3Dot( &tvec, &pvec );
	if( u < 0.0f || u > det )
		return FALSE;

	// Prepare to test V parameter
	D3DXVECTOR3 qvec;
	D3DXVec3Cross( &qvec, &tvec, &edge1 );

	// Calculate V parameter and test bounds
	FLOAT v = D3DXVec3Dot( &m_Ray.vPickRayDir, &qvec );
	if( v < 0.0f || u + v > det )
	{
		return FALSE;
	}

	// Calculate t, scale parameters, ray intersects triangle
	m_Ray.fT = D3DXVec3Dot( &edge2, &qvec );
	FLOAT fInvDet = 1.0f / det;
	m_Ray.fT *= fInvDet;
	u *= fInvDet;
	v *= fInvDet;

	m_PickPos	= m_Ray.vPickRayOrig + m_Ray.vPickRayDir * m_Ray.fT;

	return TRUE;
}
